package com.zxy.ziems.server.statistics.service.impl;

import com.zxy.ziems.server.board.constant.MysqlDateFormatEnum;
import com.zxy.ziems.server.board.pojo.vo.DosageVo;
import com.zxy.ziems.server.classify.pojo.entity.ClassifyDeviceProperty;
import com.zxy.ziems.server.classify.service.ClassifyDevicePropertyService;
import com.zxy.ziems.server.constant.DateType;
import com.zxy.ziems.server.energy.service.DeviceMeasureDataDayService;
import com.zxy.ziems.server.statistics.pojo.param.TechnologyParam;
import com.zxy.ziems.server.statistics.service.TechnologyService;
import com.zxy.ziems.server.utils.AssertUtil;
import com.zxy.ziems.server.utils.BusinessExceptionUtil;
import com.zxy.ziems.server.utils.DateUtils;
import com.zxy.ziems.server.utils.StringUtils;
import com.zxy.ziems.server.vo.ChartVo;
import com.zxy.ziems.server.vo.ChartYAxisVo;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TechnologyServiceImpl implements TechnologyService {

    @Autowired
    private DeviceMeasureDataDayService deviceMeasureDataDayService;
    @Autowired
    private ClassifyDevicePropertyService classifyDevicePropertyService;

    @Override
    public ChartVo getEnergy(TechnologyParam param) {
        Date date = getDate(param);

        LocalDate startDate = date.getStartDate();
        LocalDate endDate = date.getEndDate();

        ChartVo energyVo = new ChartVo();
        List<String> xList = DateUtils.getDateDayList(startDate, endDate, DateUtils.YMD_PATTERN);
        energyVo.setXAxisList(xList);
        // 获取分类
        List<ClassifyDeviceProperty> classifyDeviceProperties = classifyDevicePropertyService.getByClassIds(Arrays.asList(param.getDepartmentClassifyId()));
        AssertUtil.nonNull(classifyDeviceProperties, "未配置分类");
        AssertUtil.isTrue(classifyDeviceProperties.stream().map(ClassifyDeviceProperty::getDataTypeId)
                .filter(m -> m.equals(param.getEnergyType())).count() > 0, "未配置分类");
        List<DosageVo> dosageVos = deviceMeasureDataDayService.sumByDateTypeAndClassifyIds(Arrays.asList(param.getDepartmentClassifyId()),
                param.getEnergyType(), startDate, endDate, MysqlDateFormatEnum.YY_M_D.getFormat());

        List<ChartYAxisVo> yList = setChartYAxisVos(xList, dosageVos);

        energyVo.setYAxisList(yList);

        return energyVo;
    }

    @Override
    public ChartVo getProductionLine(TechnologyParam param) {
        Date date = getDate(param);

        LocalDate startDate = date.getStartDate();
        LocalDate endDate = date.getEndDate();

        ChartVo productionLineVo = new ChartVo();
        List<String> xList = DateUtils.getDateDayList(startDate, endDate, DateUtils.YMD_PATTERN);
        productionLineVo.setXAxisList(xList);
        // 获取分类
        List<ClassifyDeviceProperty> classifyDeviceProperties = classifyDevicePropertyService.getByClassIds(param.getProductionLineClassifyIds());
        AssertUtil.nonNull(classifyDeviceProperties, "未配置分类");
        List<DosageVo> dosageVos = deviceMeasureDataDayService.sumByDateTypeAndClassifyIds(param.getProductionLineClassifyIds(),
                classifyDeviceProperties.get(0).getDataTypeId(), startDate, endDate, MysqlDateFormatEnum.YY_M_D.getFormat());

        List<ChartYAxisVo> yList = setChartYAxisVos(xList, dosageVos);

        productionLineVo.setYAxisList(yList);

        return productionLineVo;
    }

    @Override
    public ChartVo getDeviceVo(TechnologyParam param) {
        Date date = getDate(param);

        LocalDate startDate = date.getStartDate();
        LocalDate endDate = date.getEndDate();

        ChartVo deviceVo = new ChartVo();
        List<String> xList = DateUtils.getDateDayList(startDate, endDate, DateUtils.YMD_PATTERN);
        deviceVo.setXAxisList(xList);
        // 获取分类
        List<ClassifyDeviceProperty> classifyDeviceProperties = classifyDevicePropertyService.getByClassIds(param.getDeviceClassifyIds());
        AssertUtil.nonNull(classifyDeviceProperties, "未配置分类");
        List<DosageVo> dosageVos = deviceMeasureDataDayService.sumByDateTypeAndClassifyIds(param.getDeviceClassifyIds(),
                classifyDeviceProperties.get(0).getDataTypeId(), startDate, endDate, MysqlDateFormatEnum.YY_M_D.getFormat());

        List<ChartYAxisVo> yList = setChartYAxisVos(xList, dosageVos);

        deviceVo.setYAxisList(yList);

        return deviceVo;
    }

    @Override
    public ChartVo getUnitVo(TechnologyParam param) {
        Date date = getDate(param);

        LocalDate startDate = date.getStartDate();
        LocalDate endDate = date.getEndDate();

        ChartVo unitVo = new ChartVo();
        List<String> xList = DateUtils.getDateDayList(startDate, endDate, DateUtils.YMD_PATTERN);
        unitVo.setXAxisList(xList);
        // 获取分类
        List<ClassifyDeviceProperty> classifyDeviceProperties = classifyDevicePropertyService.getByClassIds(param.getUnitClassifyIds());
        AssertUtil.nonNull(classifyDeviceProperties, "未配置分类");
        List<DosageVo> dosageVos = deviceMeasureDataDayService.sumByDateTypeAndClassifyIds(param.getUnitClassifyIds(),
                classifyDeviceProperties.get(0).getDataTypeId(), startDate, endDate, MysqlDateFormatEnum.YY_M_D.getFormat());

        List<ChartYAxisVo> yList = setChartYAxisVos(xList, dosageVos);

        unitVo.setYAxisList(yList);

        return unitVo;
    }

    @NotNull
    private static List<ChartYAxisVo> setChartYAxisVos(List<String> xList, List<DosageVo> dosageVos) {
        Map<String, List<DosageVo>> classifyMap = dosageVos.stream().collect(Collectors.groupingBy(DosageVo::getClassifyName));

        List<ChartYAxisVo> yList = new ArrayList<>();
        classifyMap.forEach((k, v) -> {
            ChartYAxisVo vo = new ChartYAxisVo();
            vo.setName(k);
            Map<String, BigDecimal> deviceVal = v.stream().collect(Collectors.toMap(DosageVo::getName, DosageVo::getValue));
            List<BigDecimal> data = new ArrayList<>();
            for (String s : xList) {
                data.add(deviceVal.get(s));
            }
            vo.setData(data);
            yList.add(vo);
        });
        return yList;
    }

    private Date getDate(TechnologyParam param) {
        LocalDate startDate = null;
        LocalDate endDate = null;
        if (param.getDateType().equals(DateType.DAY)) {
            startDate = DateUtils.toDate(param.getStartDate(), DateUtils.YMD_PATTERN);
            String endDate1 = param.getEndDate();
            AssertUtil.isTrue(StringUtils.isNotBlank(endDate1), "结束日期不可为空");
            endDate = DateUtils.toDate(endDate1, DateUtils.YMD_PATTERN);
        } else if (param.getDateType().equals(DateType.MONTH)) {
            startDate = DateUtils.toDate(param.getStartDate(), DateUtils.YM_PATTERN);
            endDate = DateUtils.getMonthEndDate(startDate);
        } else {
            BusinessExceptionUtil.exception("日期类型错误");
        }
        return new Date(startDate, endDate);
    }

    @Data
    @AllArgsConstructor
    class Date {
        private LocalDate startDate;
        private LocalDate endDate;
    }
}
